package net.alteiar.ui.algorithms;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;

import javax.swing.BoxLayout;
import javax.swing.JColorChooser;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.EventListenerList;

public class ColorsPanel extends JPanel {
	private static final long serialVersionUID = 1L;

	private static Random RANDOM = new Random();

	private Color generateColor() {
		return new Color(RANDOM.nextFloat(), RANDOM.nextFloat(),
				RANDOM.nextFloat(), 0.0f);
	}

	private final JSlider sliderAlpha;
	private final List<ColorLabels> colors;

	public ColorsPanel() {
		this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
		sliderAlpha = new JSlider(0, 255);
		sliderAlpha.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				fireActionPerformed();
			}
		});

		colors = new ArrayList<>();
	}

	public void setColors(int count) {
		if (count > colors.size()) {
			for (int i = 0; i < (count - colors.size()) + 1; i++) {
				colors.add(new ColorLabels());
			}
		} else if (count < colors.size()) {
			Iterator<?> itt = colors.iterator();

			for (int i = 0; i < (colors.size() - count) + 1; ++i) {
				itt.next();
				itt.remove();
			}
		}

		this.removeAll();
		this.add(sliderAlpha);
		for (ColorLabels lbl : colors) {
			this.add(lbl);
		}

		this.revalidate();
	}

	private Color addAlpha(Color c) {
		return new Color(c.getRed(), c.getGreen(), c.getBlue(),
				sliderAlpha.getValue());
	}

	public Color[] getColors() {
		Color[] result = new Color[colors.size()];
		for (int i = 0; i < colors.size(); ++i) {
			result[i] = addAlpha(colors.get(i).getColor());
		}
		return result;
	}

	/**
	 * Adds an <code>ActionListener</code> to the button.
	 * 
	 * @param l
	 *            the <code>ActionListener</code> to be added
	 */
	public void addActionListener(ActionListener l) {
		listenerList.add(ActionListener.class, l);
	}

	protected void fireActionPerformed() {
		ActionEvent event = new ActionEvent(ColorsPanel.this,
				ActionEvent.ACTION_PERFORMED, "");
		fireActionPerformed(event);
	}

	/**
	 * Notifies all listeners that have registered interest for notification on
	 * this event type. The event instance is lazily created using the
	 * <code>event</code> parameter.
	 * 
	 * @param event
	 *            the <code>ActionEvent</code> object
	 * @see EventListenerList
	 */
	protected void fireActionPerformed(ActionEvent event) {
		// Guaranteed to return a non-null array
		Object[] listeners = listenerList.getListenerList();
		ActionEvent e = null;
		// Process the listeners last to first, notifying
		// those that are interested in this event
		for (int i = listeners.length - 2; i >= 0; i -= 2) {
			if (listeners[i] == ActionListener.class) {
				// Lazily create the event:
				if (e == null) {
					String actionCommand = event.getActionCommand();
					e = new ActionEvent(ColorsPanel.this,
							ActionEvent.ACTION_PERFORMED, actionCommand,
							event.getWhen(), event.getModifiers());
				}
				((ActionListener) listeners[i + 1]).actionPerformed(e);
			}
		}
	}

	private class ColorLabels extends JPanel {
		private static final long serialVersionUID = 1L;

		private Color color;
		private final JPanel lbl;
		private final JTextField textField;

		public ColorLabels() {
			this.setLayout(new FlowLayout());

			color = addAlpha(generateColor());

			lbl = new JPanel();
			lbl.setBackground(removeAlpha(color));
			lbl.setPreferredSize(new Dimension(25, 25));
			lbl.addMouseListener(new MouseAdapter() {
				@Override
				public void mouseClicked(MouseEvent e) {
					changeColor();
				}
			});

			textField = new JTextField(3);
			this.add(lbl);
			this.add(textField);

		}

		public Color getColor() {
			return color;
		}

		private Color removeAlpha(Color c) {
			return new Color(c.getRed(), c.getGreen(), c.getBlue(), 255);
		}

		public void setColor(Color color) {
			this.color = color;

			this.lbl.setBackground(removeAlpha(color));
			this.revalidate();
			this.repaint();

			fireActionPerformed();
		}

		public void changeColor() {
			Color color = JColorChooser.showDialog(this, "Choose color",
					lbl.getBackground());
			if (color != null) {
				setColor(color);
			}
		}
	}
}
